package com.test.utils;

import cn.hutool.json.JSONUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.test.properties.AliPayProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝支付工具类
 * 提供了app支付、服务器通知验证、退款、交易查询和下载对账单等功能
 */
@Slf4j
@Component
public class AliPayUtil {

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    AliPayProperties aliPayProperties;

    /**
     * 生成app支付链接
     *
     * @param model 支付相关业务参数
     * @return 支付宝返回的支付页面HTML内容
     */
    public String appPay(AlipayTradeWapPayModel model){
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        request.setBizModel(model);
        request.setReturnUrl(aliPayProperties.getReturnUrl());
        request.setNotifyUrl(aliPayProperties.getNotifyUrl());
        AlipayTradeWapPayResponse response;
        try {
            response = alipayClient.pageExecute(request);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        return response.getBody();
    }

    /**
     * 服务器异步通知页面
     *
     * @param request HTTP请求对象，包含支付宝返回的异步通知参数
     * @return 验证通过的参数Map，验签失败返回null
     */
    public Map<String, String> notifyServer(HttpServletRequest request){
        Map<String, String> map = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            map.put(name, valueStr);
        }

        // 验证支付宝数字签名
        boolean signVerified;
        try {
            signVerified = AlipaySignature.rsaCheckV1(map, aliPayProperties.getAliPayPublicKey(), aliPayProperties.getCharset(), aliPayProperties.getSignType());
            if (signVerified) {
                return map;
            } else {
                log.info("[支付回调] 验签失败");
                return null;
            }
        } catch (com.alipay.api.AlipayApiException e) {
            log.info("[支付验证] 异常={}", JSONUtil.parse(e));
        }

        return null;
    }

    /**
     * 退款操作
     *
     * @param model 退款相关业务参数
     * @return 支付宝返回的退款信息
     */
    public String refund(AlipayTradeRefundModel model){
        AlipayTradeRefundRequest alipayRefund = new AlipayTradeRefundRequest();
        alipayRefund.setBizModel(model);
        AlipayTradeRefundResponse execute;
        try {
            execute = alipayClient.execute(alipayRefund);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        return execute.getBody();
    }

    /**
     * 查询交易状态
     *
     * @param model 交易查询相关业务参数
     * @return 支付宝返回的交易状态信息
     */
    public String queryTrade(AlipayTradeQueryModel model){
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizModel(model);
        AlipayTradeQueryResponse execute;
        try {
            execute = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        return execute.getBody();
    }

    /**
     * 获取对账单下载链接
     *
     * @param model 对账单请求参数
     * @return 支付宝返回的对账单下载链接
     */
    public String bill(AlipayDataDataserviceBillDownloadurlQueryModel model){
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
        request.setBizModel(model);
        AlipayDataDataserviceBillDownloadurlQueryResponse execute;
        try {
            execute = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            throw new RuntimeException(e);
        }

        return execute.getBody();
    }
}
